package com.zhl.study.controller;

import com.zhl.study.constant.AuthServerConstant;
import com.zhl.study.entity.User;
import com.zhl.study.interceptor.LoginUserInterceptor;
import com.zhl.study.service.AccountService;
import com.zhl.study.service.DealService;
import com.zhl.study.service.LoginService;
import com.zhl.study.base.ResponseFactory;
import com.zhl.study.base.Result;
import com.zhl.study.util.ThreadSafeFormatterUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @description TODO
 * @Author: z156940l@outlook.com
 * @className WebController
 * @Date: 2023/4/28 17:53
 */
@RestController
@RequestMapping("api/")
@Api(value = "ThreadLocal应用场景", tags = "ThreadLocal应用场景")
public class WebController {


    @Autowired
    private AccountService accountService;

    /**
     * ThreadLocal实战 代码演示 工作中是怎么使用的
     * demo1 每个线程绑定一个连接 实现线程内隔离 控制事务
     *
     * @return
     */
    @GetMapping("transfer")
    @ApiOperation(httpMethod = "GET", value = "第一种数据库连接池的管理")
    public Result<Void> transfer() {
        // 模拟数据 : zhaolin 给 lili 转账 100
        String outUser = "linlin";
        String inUser = "lili";
        int money = 100;

        boolean result = accountService.transfer(outUser, inUser, money);

        if (!result) {
            System.out.println("转账失败!");
        } else {
            System.out.println("转账成功!");
        }
        return ResponseFactory.ok();
    }


    @Autowired
    private LoginService loginService;

    /**
     * demo2 每个线程内需要保存全局变量（例如在拦截器中获取用户信息），可以让不同方法直接使用，避免参数传递的麻烦
     *
     * @return
     */
    @GetMapping("login")
    @ApiOperation(httpMethod = "GET", value = "第二种模拟用户登录，将登录信息放入到session中，登录方法")
    public Result<Void> login(@RequestParam String userName, @RequestParam String passWord, HttpServletRequest httpServletRequest) {

        //用户登录 返回实体类
        User userLogin = loginService.login(userName, passWord);

        //放入session中
        HttpSession session = httpServletRequest.getSession();
        session.setAttribute(AuthServerConstant.LOGIN_USER, userLogin);

        return ResponseFactory.ok();
    }


    /**
     * 获得用户信息  localhost:8080/app/getUser
     *
     * @return
     */
    @GetMapping("getUser")
    @ApiOperation(httpMethod = "GET", value = "第二种模拟用户登录，将登录信息放入到session中，获取用户方法")
    public Result<User> getUser() {

        User user = LoginUserInterceptor.loginUser.get();
        return ResponseFactory.ok(user);
    }


    @Autowired
    private DealService dealService;

    /**
     * demo3 在方法调用的过程中 用来代替参数传值！
     *
     * @return
     */
    @GetMapping("dealTransfer")
    @ApiOperation(httpMethod = "GET", value = "第三种方法传值，避免多层方法传递，代码冗余")
    public Result<Void> dealTransfer() {

        dealService.dealTransfer();
        return ResponseFactory.ok();
    }


    /**
     * demo4 每个线程需要一个独享对象（通常是工具类，典型需要使用的类有SimpleDateFormat）
     * 每个Thread内有自己的实例副本，不共享
     *
     * @return
     */
    @GetMapping("dealDate")
    @ApiOperation(httpMethod = "GET", value = "第四种方法线程不安全的类的使用，例如SimpleDateFormat")
    public Result<Void> dealDate() {

        for (int i = 0; i < 30; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    SimpleDateFormat simpleDateFormat = ThreadSafeFormatterUtil.dateFormatThreadLocal.get();
                    String date = simpleDateFormat.format(new Date());
                    System.out.println(date);
                }
            }).start();
        }
        return ResponseFactory.ok();
    }


}